package cn.springcloud.alibaba.gateway.route;

import cn.springcloud.alibaba.core.constant.Constant;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionRepository;
import org.springframework.cloud.gateway.support.NotFoundException;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.util.ArrayList;
import java.util.List;

/**
 * 实现动态路由
 */
@Slf4j
@Component
public class JdbcRouteDefinitionRepository implements RouteDefinitionRepository, ApplicationEventPublisherAware {

	private ApplicationEventPublisher publisher;

	@Autowired
	private StringRedisTemplate stringRedisTemplate;
	// @Autowired
	// private SysGatewayRouteMapper sysGatewayRouteMapper;

	@Override
	public void setApplicationEventPublisher(ApplicationEventPublisher publisher) {
		this.publisher = publisher;
	}

	/**
	 * 监听事件刷新配置
	 */
	/*@EventListener
	public void listenEvent(RouteConfigRefreshEvent event) {
		loadRouteDefinitions();
		this.publisher.publishEvent(new RefreshRoutesEvent(this));
	}*/
	private List<RouteDefinition> loadRouteDefinitions() {
		List<RouteDefinition> routeDefinitions = new ArrayList<>();

		try {
			// 先从redis加载，redis取不到再从数据库加载
			stringRedisTemplate.opsForHash().values(Constant.GATEWAY_ROUTE_KEY).forEach(e -> {
				routeDefinitions.add(JSON.parseObject((String) e, RouteDefinition.class));
			});

			/*if (CollectionUtils.isNotEmpty(routeDefinitions)) {
				log.info("-------------- 从redis中加载路由配置 ---------------");
				return routeDefinitions;
			}

			log.info("-------------- 从数据库中加载配置 ---------------");

			List<SysGatewayRoute> routes = sysGatewayRouteMapper.selectList(
				Wrappers.<SysGatewayRoute>lambdaQuery().eq(SysGatewayRoute::getStatus, 0)
			);

			if (CollectionUtils.isEmpty(routes)) {
				return routeDefinitions;
			}

			Map<String, String> param = new HashMap<>();
			for (SysGatewayRoute gatewayRoute : routes) {
				RouteDefinition routeDefinition = this.assembleRouteDefinition(gatewayRoute);
				param.put(routeDefinition.getId(), JSON.toJSONString(routeDefinition));
				routeDefinitions.add(routeDefinition);
			}*/

			// stringRedisTemplate.opsForHash().putAll(Constant.GATEWAY_ROUTE_KEY, param);
			return routeDefinitions;
		} catch (Exception e) {
			log.error("从数据库中加载配置", e);
			return routeDefinitions;
		}
	}

/*	private RouteDefinition assembleRouteDefinition(SysGatewayRoute route) {
		RouteDefinition routeDefinition = new RouteDefinition();
		routeDefinition.setId(route.getRouteId());
		routeDefinition.setOrder(route.getSortOrder());
		routeDefinition.setUri(URI.create(route.getRouteUri()));
		Map<String, Object> metadata = JSON.parseObject(route.getMetadata(), HashMap.class);
		routeDefinition.setMetadata(metadata);
		//获取过滤器集合
		if (StringUtils.isNotEmpty(route.getFilters())) {
			List<FilterDefinition> definitions = JSON.parseArray(route.getFilters(), FilterDefinition.class);
			routeDefinition.setFilters(definitions);
		}
		//获取断言集合
		if (StringUtils.isNotEmpty(route.getPredicates())) {
			List<PredicateDefinition> definitions = JSON.parseArray(route.getPredicates(), PredicateDefinition.class);
			routeDefinition.setPredicates(definitions);
		}
		return routeDefinition;
	}*/

	@Override
	public Mono<Void> save(Mono<RouteDefinition> route) {
		return Mono.defer(() -> Mono.error(new NotFoundException("Unsupported operation")));
	}

	@Override
	public Mono<Void> delete(Mono<String> routeId) {
		return Mono.defer(() -> Mono.error(new NotFoundException("Unsupported operation")));
	}

	@Override
	public Flux<RouteDefinition> getRouteDefinitions() {
		return Flux.fromIterable(loadRouteDefinitions());
	}
}

